package com.xxwu.springgobang.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xxwu.springgobang.component.Matcher;
import com.xxwu.springgobang.component.OnlineUserManager;
import com.xxwu.springgobang.component.MatchRequest;
import com.xxwu.springgobang.component.MatchResponds;
import com.xxwu.springgobang.model.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.Resource;

@Slf4j
@RestController("match")
public class MatchController extends TextWebSocketHandler {

    private ObjectMapper objectMapper = new ObjectMapper();
    @Resource
    private OnlineUserManager onlineUserManager;

    @Resource
    private Matcher matcher;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //连接建立，拿到用户信息，将玩家状态设置成上线
        //这里能够拿到user信息是因为玩家登陆时，在 http 响应中设置了 Session 信息
        //而在注册 WebSocket API 时使用 .addInterceptors(new HttpSessionHandshakeInterceptor());
        //将 Http 中的信息放在了 WebSocket 的Session 中
        try{
            //当用户未登录就直接访问gobang_gamehall.html，此时获取不到user信息，会报空指针异常
            User user = (User) session.getAttributes().get("user");
            //防止多开
            //当前用户已经登陆了
            if(onlineUserManager.getSessionFromGameHall(user.getUserId()) != null
            ||onlineUserManager.getSessionFromGameRoom(user.getUserId()) != null){
                log.info("getSessionFromGameHall:{}",onlineUserManager.getSessionFromGameHall(user.getUserId()));
                log.info("getSessionFromGameRoom{},玩家{}",onlineUserManager.getSessionFromGameRoom(user.getUserId()),user.getUsername());
                MatchResponds responds = new MatchResponds();
                responds.setReason("您的账号在其他设备已登录");
                responds.setOk(true);
                responds.setMessage("repeatConnection");
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(responds)));
                //关闭连接，后续逻辑不再执行
                //直接关闭不能够清楚的表明当前是因为多开关闭还是因为页面跳转关闭连接
                //session.close();
                return;
            }
            onlineUserManager.enterGameHall(user.getUserId(), session);
            log.info("玩家{}进入游戏大厅！", user.getUsername());
        } catch (NullPointerException e){
            log.info("MatchController.afterConnectionEstablished 当前用户未登录!");
            // 以下内容是连接关闭后执行的操作，会抛出异常
            //将错误信息包装成Respond对象进行返回
//            MatchResponds respond = new MatchResponds();
//            respond.setOk(false);
//            respond.setReason("进入游戏大厅失败!请登录后进入");
//
//            //在将信息传送会客户端时，将Java转化为JSON字符串
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(respond)));
        }

    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        User user = (User) session.getAttributes().get("user");

        //将获取到的JSON格式的 message 转换为 WebSocketResponds
        MatchRequest request = objectMapper.readValue(message.getPayload(), MatchRequest.class);
        MatchResponds respond = new MatchResponds();

//        log.info("request:{}", request);
        //对客户端发来的数据进行处理
        if(request.getMessage().equals("startMatch")){
            // 将用户放进匹配队列
            matcher.add(user);
            respond.setMessage("startMatch");
        } else if(request.getMessage().equals("stopMatch")){
            // 将用户从匹配队列中移除
            matcher.remove(user);
            respond.setMessage("stopMatch");
        } else {
            respond.setOk(false);
            respond.setReason("非法的匹配请求");
        }
        log.info("respond: {}", respond);
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(respond)));
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        try{
            User user = (User) session.getAttributes().get("user");
            //获取enterHall中存储的session，与当前session进行对比，若一致才能执行退出当前user
            //否则可能因为多开误伤原先的登陆情况
            WebSocketSession tmpSession = onlineUserManager.getSessionFromGameHall(user.getUserId());
            if(tmpSession == session){
                onlineUserManager.exitGameHall(user.getUserId());
                matcher.remove(user);
                log.info("玩家{}因连接异常离开游戏大厅！", user.getUsername());
            }
        } catch (NullPointerException e){
            log.info("MatchController.handleTransportError 当前用户未登录!");
            //下面同样不应在连接关闭后尝试给服务器发送消息
            //将错误信息包装成Respond对象进行返回
//            MatchResponds respond = new MatchResponds();
//            respond.setOk(false);
//            respond.setReason("进入游戏大厅失败!请登录后进入");
//
//            //在将信息传送会客户端时，将Java转化为JSON字符串
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(respond)));
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        try{
            User user = (User) session.getAttributes().get("user");
            WebSocketSession tmpSession = onlineUserManager.getSessionFromGameHall(user.getUserId());
            if(tmpSession == session){
                onlineUserManager.exitGameHall(user.getUserId());
                matcher.remove(user);
                log.info("玩家{}离开游戏大厅！连接关闭", user.getUsername());
            }
        } catch (NullPointerException e){
            log.info("MatchController.afterConnectionClosed 当前用户未登录!");
            //不应该在连接关闭之后还发送消息给客户端，这里会导致服务器报错
//            //将错误信息包装成Respond对象进行返回
//            MatchResponds respond = new MatchResponds();
//            respond.setOk(false);
//            respond.setReason("进入游戏大厅失败!请登录后进入");
//
//            //在将信息传送会客户端时，将Java转化为JSON字符串
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(respond)));
        }
    }


}
